<?php

namespace App\Http\Controllers\Account;

use Exception;
use App\Models\User;
use App\Models\Audit;
use App\Models\Station;
use App\Models\Personal;
use App\Models\Inspection;
use Illuminate\Http\Request;
use App\Models\Station\Report;
use App\Models\Inspection\Node;
use App\Models\Inspection\Line;
use App\Jobs\Push\UpdateUserAlias;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;
use Illuminate\Support\Facades\Storage;
use App\Repositories\InspectionRepository;
use App\Repositories\AttendanceRepository;
use App\Http\Requests\User\Personal\JoinCompany;
use App\Http\Requests\User\Personal\ReportStation;
use App\Http\Requests\User\Personal\ModifyProfile;
use App\Http\Requests\User\Personal\InspectionRequest;
use App\Http\Requests\Account\Attendance\SigninRequest;
use App\Http\Requests\User\Personal\ModifyIdentification;

/**
 * 用户业务逻辑控制器
 *
 * Date: 20/03/2018
 * @author George
 * @package App\Http\Controllers\Account
 */
class PersonalController extends Controller
{
	protected $userRepository;
	protected $attendanceRepository;
	protected $inspectionRepository;

	/**
	 * PersonalController constructor.
	 * @param UserRepository $userRepository
	 * @param AttendanceRepository $attendanceRepository
	 * @param InspectionRepository $inspectionRepository
	 */
	public function __construct(
		UserRepository $userRepository,
		AttendanceRepository $attendanceRepository,
		InspectionRepository $inspectionRepository
	)
	{
		$this->userRepository = $userRepository;
		$this->attendanceRepository = $attendanceRepository;
		$this->inspectionRepository = $inspectionRepository;
	}

	/**
	 * 获取用户信息
	 *
	 * Date: 29/04/2018
	 * @author George
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function profile()
	{
		$user = Auth::user();
		$user->getCompany();
		return success($user);
	}

	/**
	 * 绑定用户的唯一通知ID
	 *
	 * Date: 2018/6/2
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function bindRegistrationID(Request $request)
	{
		$attributes = $this->validate($request, [
			'registration_id' => 'required'
		]);
		try {
			$user = Auth::user();
			$user->update($attributes);
			/**
			 * 异步绑定
			 */
			dispatch(new UpdateUserAlias($user));
			return updated($user, '绑定 Registration ID 成功');
		} catch (Exception $exception) {
			Log::error($exception);
			return internalError('绑定 Registration ID 失败');
		}
	}

	/**
	 * 获取用户的排班信息
	 *
	 * Date: 06/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function schedule(Request $request)
	{
		/**
		 * @var User $user
		 */
		$user = $request->user();
		$schedule = $user->getSchedule();
		if ($schedule) {
			$attendance = $user->getAttendance();
			$schedule->offsetSet('checkin', optional($attendance)->checkin_time);
			$schedule->offsetSet('checkout', optional($attendance)->checkout_time);
			return success($schedule);
		}
		return notFound('未找到排班记录');
	}

	/**
	 * 修改头像
	 *
	 * Date: 21/03/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \Throwable
	 */
	public function modifyAvatar(Request $request)
	{
		$this->validate($request, [
			'avatar' => 'required|image|mimes:jpeg,png|dimensions:max_width=512,max_height=512'
		], [
			'avatar.required' => '请选择要用作头像的图片',
			'avatar.image' => '只能上传图片格式',
			'avatar.mimes' => '只支持JPG和PNG格式的图片',
			'avatar.dimensions' => '图片宽高不得超过512像素',
		]);

		try {
			$file = $request->file('avatar');
			$path = $file->store('avatar', 'public');
			$url = Storage::url($path);
		} catch (Exception $exception) {
			return internalError();
		}

		$this->userRepository->modifyAvatar($url, $request->user());
		return updated(['avatar' => $url], '头像修改成功');
	}

	/**
	 * 修改密码
	 *
	 * Date: 21/03/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \Throwable
	 */
	public function modifyPassword(Request $request)
	{
		$params = $this->validate($request, [
			'old_password' => 'required',
			'new_password' => 'required',
		], [
			'old_password.required' => '请输入旧密码',
			'new_password.required' => '请输入新密码',
		]);

		$result = $this->userRepository->modifyPassword($params['old_password'], $params['new_password'], $request->user());

		if ($result) {
			return updated('您的密码修改成功');
		}

		return failed('您输入的旧密码有误，修改密码失败！');
	}

	/**
	 * 修改用户身份信息
	 *
	 * Date: 11/04/2018
	 * @author George
	 * @param ModifyIdentification $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \App\Exceptions\GeneralException
	 */
	public function modifyIdentification(ModifyIdentification $request)
	{
		$personal = $request->only([
			'name',
			'gender',
			'birthday',
			'identification',
		]);

		$identification = $request->only([
			'issuer',
			'hometown',
			'identification',
			'identification_front',
			'identification_reverse'
		]);

		$this->userRepository->updateByPrimary(Auth::id(), $personal);
		$result = $this->userRepository->modifyIdentification($identification);
		return updated($result);
	}

	/**
	 * 补全用户信息
	 *
	 * Date: 27/04/2018
	 * @author George
	 * @param ModifyProfile $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \App\Exceptions\GeneralException
	 */
	public function modifyProfile(ModifyProfile $request)
	{
		$attributes = $this->extractInputFromRules($request, $request->rules());
		$user = Auth::user();
		try {
			$personal = Personal::updateOrCreate(['identification' => $user->identification], $attributes);
		} catch (Exception $exception) {
			Log::error($exception);
			return failed('无法保存你的个人信息，请稍后再试');
		}
		return stored($personal);
	}

	/**
	 * 获取用户最后加入公司申请记录
	 *
	 * Date: 03/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function joinStatus(Request $request)
	{
		$user = Auth::user();
		$audit = $user->joins()->latest()->first();
		return success($audit);
	}

	/**
	 * 用户打卡
	 *
	 * Date: 17/04/2018
	 * @author George
	 * @param SigninRequest $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function signin(SigninRequest $request)
	{
		$attributes = $request->all();
		$attendance = $this->attendanceRepository->createOrUpdate($attributes);
		return success($attendance);
	}

	/**
	 * 加入公司
	 *
	 * Date: 27/04/2018
	 * @author George
	 * @param JoinCompany $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function joinCompany(JoinCompany $request)
	{
		$company_id = $request->get('company_id');

		$user = Auth::user();

		$record = $user->joins()->where('status', 'pending')->latest()->first();
		// 判断是否有待审批的申请记录
		if ($record) {
			return failed('你已经提交了一个申请，请耐心等待审核结果', 422);
		}

		$career = DB::table('company_user_pivot')->where('user_id', $user->id)->whereNull('departure_at')->first();
		// 判断是否存在未离职的记录
		if ($career) {
			return failed('存在未结束的劳务关系，无法申请加入其它公司', 422);
		}

		$attributes = [
			'auditable_id' => Auth::id(),
			'auditable_type' => 'user',
			'proposer' => Auth::id(),
			'company_id' => $company_id,
		];
		$audit = Audit::create($attributes);
		return success($audit);
	}

	/**
	 * 创建巡检记录
	 *
	 * Date: 01/05/2018
	 * @author George
	 * @param InspectionRequest $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \App\Exceptions\GeneralException
	 */
	public function inspection(InspectionRequest $request)
	{
		$attributes = $this->extractInputFromRules($request, $request->rules());
		array_pull($attributes, 'images');
		$user = Auth::user();
		$line = Line::findOrFail($attributes['line_id']);
		$node = Node::findOrFail($attributes['node_id']);
		$time = DB::table('circle_node_pivot')
			->select('time')
			->where('line_id', $line->id)
			->where('circle_id', $attributes['circle_id'])
			->where('node_id', $node->id)->first();

		$now = time();
		$node_time = strtotime(date('Y-m-d ' . $time->time));

		// 判断是否在误差范围内
		if (($now - $line->mistiming) > $node_time || ($now + $line->mistiming) < $node_time) {
			$attributes['status'] = false;
		}

		$schedule = $user->getSchedule();
		$attributes['schedule_id'] = $schedule->id;
		$attributes['node_name'] = $node->name;
		$attributes['company_id'] = $user->company_id;
		$attributes['user_id'] = $user->id;
		$attributes['user_name'] = $user->name;

		$record = Inspection::query()->where([
			['schedule_id', '=', $schedule->id],
			['line_id', '=', $attributes['line_id']],
			['circle_id', '=', $attributes['circle_id']],
			['node_id', '=', $attributes['node_id']]
		])->count();

		if ($record > 0) {
			return failed('该点位今天已完成巡检，无法多次提交记录');
		}

		$time = DB::table('circle_node_pivot')->select('time')->where([
			['line_id', '=', $attributes['line_id']],
			['circle_id', '=', $attributes['circle_id']],
			['node_id', '=', $attributes['node_id']]
		])->first();

		// 线路允许误差：单位秒
		$mistiming = $line->mistiming * 60;
		$now = time();
		$range_start = strtotime($time->time) - $mistiming;
		$range_end = strtotime($time->time) + $mistiming;
		// 判断巡检时间是否在有效范围内
		$status = $now > $range_start && $now < $range_end;

		if ($time && $status) {
			$attributes['status'] = 1;
		} else {
			$attributes['status'] = 0;
		}

		$inspection = $this->inspectionRepository->store($attributes, $request->file('images'));

		return stored($inspection);
	}

	/**
	 * 人员报岗
	 *
	 * Date: 2018/5/28
	 * @author George
	 * @param ReportStation $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function station(ReportStation $request)
	{
		$attributes = $this->extractInputFromRules($request, $request->rules());
		$station = Station::with('project')->where('id', $attributes['station_id'])->firstOrFail();
		$user = Auth::user();
		$attributes['company_id'] = $station->company_id;
		$attributes['project_id'] = $station->project_id;
		$attributes['project_name'] = optional($station->project)->name;
		$attributes['user_id'] = $user->id;
		$attributes['user_name'] = $user->name;
		array_pull($attributes, 'image');
		$image = $request->file('image', false);

		if (!$image) {
			return failed('图片有误', 422);
		}

		$path = $image->store('public/station');
		$attributes['image'] = Storage::url($path);
		// 创建报岗记录
		$report = Report::create($attributes);
		return stored($report);
	}
}
